package com.yckj.ytracker.api.trace;


import com.yckj.ytracker.api.collect.SpanCollector;
import com.yckj.ytracker.api.config.Global;
import com.yckj.ytracker.api.model.Span;
import com.yckj.ytracker.api.model.TrackerData;
import com.yckj.ytracker.api.util.IdGenerator;

public class TracerServer implements ITracerServer {

    private final TraceContext context;
    private final SpanCollector collector;

    public TracerServer(final TraceContext context, final SpanCollector collector) {
        this.context = context;
        this.collector = collector;
    }

    @Override
    public Span startNewSpan(String clusterName, String type, String funcName, String param) {
        final Span newSpan = new Span();
        newSpan.setLocalIp(Global.getInstance().getLocalIp());
        newSpan.setSpanId(String.valueOf(IdGenerator.newSpanId()));
        newSpan.setTraceId(IdGenerator.createTraceId());
        newSpan.setClusterName(clusterName);
        newSpan.setParam(param);
        newSpan.setType(type);
        newSpan.setFuncName(funcName);
        newSpan.setRootName(clusterName);
        context.setCurrentSpan(newSpan);
        context.setParentSpan(newSpan);
        return newSpan;
    }

    @Override
    public void startNewSpan(String clusterName, String type, String func, String param, TrackerData trackerData) {
        final Span newSpan = new Span();
        newSpan.setLocalIp(Global.getInstance().getLocalIp());
        newSpan.setSpanId(trackerData.getSpanId());
        newSpan.setTraceId(trackerData.getTraceId());
        newSpan.setClusterName(clusterName);
        newSpan.setType(type);
        newSpan.setParam(param);
        newSpan.setFuncName(func);
        newSpan.setRootName(trackerData.getRootName());
        context.setCurrentSpan(newSpan);
        context.setParentSpan(newSpan);
    }

    @Override
    public Span startChildSpan(String type, String func, String param) {
        final Span span = context.getCurrentSpan();
        if (span != null) {
            Span newSpan = new Span();
            newSpan.setSpanId(span.nextChildTrackId());
            newSpan.setTraceId(span.getTraceId());
            newSpan.setType(type);
            newSpan.setClusterName(span.getClusterName());
            newSpan.setParam(param);
            newSpan.setParentSpan(null);
            newSpan.setFuncName(func);
            newSpan.setLocalIp(span.getLocal().getHost());
            newSpan.setAttributes(span.getAttributes());
            newSpan.setRootName(span.getRootName());
            context.setCurrentSpan(newSpan);
            context.setParentSpan(newSpan);
            return newSpan;
        }
        return null;
    }

    @Override
    public void setSpanSent() {
        final Span span = context.getCurrentSpan();
        if (span != null) {
            span.setTime(System.currentTimeMillis());
            span.setCost(System.nanoTime());
            context.setParentSpan(span);
        }
    }

    @Override
    public void setSpanReceived() {
        final Span currentSpan = context.getCurrentSpan();
        if (currentSpan != null) {
            currentSpan.setCost((System.nanoTime() - currentSpan.getCost()));
            collector.collect(currentSpan);
            context.setCurrentSpan(null);
            context.setParentSpan(context.getCurrentSpan());
        }
    }

    @Override
    public Span getSpan() {
        return context.getCurrentSpan();
    }

    @Override
    public void clearCurrentSpan() {
        context.setCurrentSpan(null);
        context.setParentSpan(context.getCurrentSpan());
    }

    @Override
    public void collectAllSpan() {
        context.refresh();
    }
}